feat!: make listeners passive, implement all implicit events#158
Merged
feat!: make listeners passive, implement all implicit events#158
Conversation
@affects atoms, immer, machines, react, stores
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@affects atoms, immer, machines, react, stores
Description
Introduce the concept of "passive" and "active" event listeners. Make listeners passive by default, which means they don't influence the node's lifecycle. Add the
{ active: true }ListenerConfig option for explicitly influencing lifecycle changes (this mimics the oldinstance.addDependentmethod - while the active listener is attached, it prevents automatic destruction. When removed, Zedux checks the ref count of the node and schedules destruction if needed).Implicit Events
Finish implementing all implicit event types. They are officially:
change. Listeners receive aChangeEventwithnewStateandoldStateproperties.cycle. Listeners receive aCycleEventwithnewStatusandoldStatusproperties.invalidate. Listeners receive anInvalidateEventwith no unique own properties (useevent.sourceto access the invalidated node).promiseChange. Listeners receive aPromiseChangeEventwith no unique own properties (useevent.source.promiseto access the new promise).All implicit events also have these properties:
Explicit Events
Test and handle tons of edge cases around the
mutateevent. It's going to be much less common to attach listeners to inner signals than outer signals (or the whole atom) for relaying transactions e.g. to other realms or data grids. Because of this:mutateevent is sent to inner signals - they weren't mutated, the outer signal was.mutateevent is sent to the outer signal. This mutate event's transactions are modified to include the key path to the inner signal.mutateis the only explicit event.batchis scrapped. It isn't possible to set a node's state and defer running its dependents. That was possible with stores since stores weren't graph nodes, but it still wasn't good - the store's state would be temporarily, visibly out of sync with its dependent atom until the scheduler ran on the next tick. This state tearing is not something we can allow in the atom graph at all - Zedux's atomic model is glitchless.We could defer callback functions before allowing
.setcalls etc to update any node state. But it's such a rare use case and very easy for users to create abatchAtomthat does that if needed - stores callback functions and runs them later. Since it's rarely used and easy to do manually or via an addon, Zedux should not include this functionality in its core.Other Stuff
Finally(!) fix scheduler flushes in potentially recursive
.set,.mutate,handleStateChange,.sendcalls. Introducescheduler.preandscheduler.postwhich function as essentially anecosystem.batch()call without the need to create a closure. This fixed lots of new edge cases introduced with recursive mapped signals.Guarantee listener call order based on graph node weight and order added. Inner signal listeners always run before outer signal listeners. Multiple listeners on the same node and event type (or different event types that are sent together) run in the order they were added in.
Add tests for complicated nesting configurations involving atoms and signals in other atoms and signals. Add tests for all implicit event types.
Issues
Resolves #115